home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / slip / cslip-2.6 / tip / libacu / hayes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-30  |  9.0 KB  |  463 lines

  1. #ifndef lint
  2. static char rcsid[] =
  3.     "@(#) $Header: hayes.c,v 1.5 90/06/30 17:29:13 leres Exp $ (LBL)";
  4. #endif
  5. /*
  6.  * Copyright (c) 1983 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms are permitted
  10.  * provided that: (1) source distributions retain this entire copyright
  11.  * notice and comment, and (2) distributions including binaries display
  12.  * the following acknowledgement:  ``This product includes software
  13.  * developed by the University of California, Berkeley and its contributors''
  14.  * in the documentation or other materials provided with the distribution
  15.  * and in all advertising materials mentioning features or use of this
  16.  * software. Neither the name of the University nor the names of its
  17.  * contributors may be used to endorse or promote products derived
  18.  * from this software without specific prior written permission.
  19.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  21.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  22.  */
  23.  
  24. #ifndef lint
  25. static char sccsid[] = "@(#)hayes.c    5.2 (Berkeley) 9/13/88";
  26. #endif /* not lint */
  27.  
  28. /*
  29.  * Routines for calling up on a Hayes Modem
  30.  * (based on the old VenTel driver).
  31.  * The modem is expected to be strapped for "echo".
  32.  * Also, the switches enabling the DTR and CD lines
  33.  * must be set correctly.
  34.  * NOTICE:
  35.  * The easy way to hang up a modem is always simply to
  36.  * clear the DTR signal. However, if the +++ sequence
  37.  * (which switches the modem back to local mode) is sent
  38.  * before modem is hung up, removal of the DTR signal
  39.  * has no effect (except that it prevents the modem from
  40.  * recognizing commands).
  41.  * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984)
  42.  */
  43. /*
  44.  * TODO:
  45.  * It is probably not a good idea to switch the modem
  46.  * state between 'verbose' and terse (status messages).
  47.  * This should be kicked out and we should use verbose
  48.  * mode only. This would make it consistent with normal
  49.  * interactive use thru the command 'tip dialer'.
  50.  */
  51.  
  52. #include "tip.h"
  53. #include <sys/time.h>
  54.  
  55.  
  56. static char MDM_OK[] = "\nOK\r";
  57. static char RRING[] = "RRING\r\n";
  58. static char CONNECT[] = "CONNECT";    /* generic prefix */
  59.  
  60. #define    CMD_DELAY    5    /* number of seconds to wait for response
  61.                  * while in command mode */
  62. #define DIAL_DELAY    120    /* number of seconds to wait for response
  63.                  * after sending dial string */
  64. #define WRITE_DELAY    100    /* ms between each character written to modem */
  65. #define    MAXSTR    256
  66.  
  67. #define    min(a,b)    ((a < b) ? a : b)
  68.  
  69. static    int sigALRM();
  70. static    int timeout = 0;
  71. static    jmp_buf timeoutbuf;
  72. static    char gobble();
  73.  
  74. #define    DIALING        1
  75. #define IDLE        2
  76. #define CONNECTED    3
  77. #define    FAILED        4
  78. static    int state = IDLE;
  79.  
  80. static void hywrite();
  81. static void hyerrputc();
  82. static void hyerrputs();
  83. static int hyread();
  84. static char hygetc();
  85.  
  86. hay_dialer(num, acu)
  87.     register char *num;
  88.     char *acu;
  89. {
  90.     register char *cp;
  91.     register int connected = 0;
  92.     char dummy;
  93. #ifdef ACULOG
  94.     char line[80];
  95. #endif
  96.     if (hay_sync() == 0)        /* make sure we can talk to the modem */
  97.         return(0);
  98.     if (boolean(value(VERBOSE))) {
  99.         (void) printf("dialing... ");
  100.         if (debug)
  101.             putchar('\n');
  102.         (void) fflush(stdout);
  103.     }
  104.     fflush(stdout);
  105.     ioctl(FD, TIOCHPCL, 0);
  106.     ioctl(FD, TIOCFLUSH, 0);    /* get rid of garbage */
  107.     hywrite("ATv0\r");    /* tell modem to use short status codes */
  108.     gobble("\r");
  109.     gobble("\r");
  110.     hywrite("ATTD");    /* send dial command */
  111.     hywrite(num);
  112.     state = DIALING;
  113.     hywrite("\r");
  114.     connected = 0;
  115.     if (gobble("\r")) {
  116.         if ((dummy = gobble("012345")) != '1' && dummy != '5')
  117.             error_rep(dummy);
  118.         else
  119.             connected = 1;
  120.     }
  121.     if (connected)
  122.         state = CONNECTED;
  123.     else {
  124.         state = FAILED;
  125.         return (connected);    /* lets get out of here.. */
  126.     }
  127.     ioctl(FD, TIOCFLUSH, 0);
  128. #ifdef ACULOG
  129.     if (timeout) {
  130.         sprintf(line, "%d second dial timeout",
  131.             number(value(DIALTIMEOUT)));
  132.         logent(value(HOST), num, "hayes", line);
  133.     }
  134. #endif
  135.     if (timeout)
  136.         hay_disconnect();    /* insurance */
  137.     return (connected);
  138. }
  139.  
  140.  
  141. hay_disconnect()
  142. {
  143.     char c;
  144.     int len, rlen;
  145.  
  146.     /* first hang up the modem*/
  147. #ifdef DEBUG
  148.     printf("\rdisconnecting modem....\n\r");
  149. #endif
  150.     ioctl(FD, TIOCCDTR, 0);
  151.     sleep(1);
  152.     ioctl(FD, TIOCSDTR, 0);
  153.     goodbye();
  154. }
  155.  
  156. hay_abort()
  157. {
  158.  
  159.     char c;
  160.  
  161.     hywrite("\r");    /* send anything to abort the call */
  162.     hay_disconnect();
  163. }
  164.  
  165. static int
  166. sigALRM()
  167. {
  168.  
  169.     printf("\07timeout waiting for reply\n\r");
  170.     timeout = 1;
  171.     longjmp(timeoutbuf, 1);
  172. }
  173.  
  174. static char
  175. gobble(match)
  176.     register char *match;
  177. {
  178.     char c;
  179.     int (*f)();
  180.     int i, status = 0;
  181.     int timeout = number(value(DIALTIMEOUT));
  182.  
  183.     if (debug) {
  184.         fputs("<? \"", stderr);
  185.         hyerrputs(match);
  186.         fputs("\"\n<- \"", stderr);
  187.         (void) fflush(stderr);
  188.     }
  189.     do {
  190.         c = hygetc(timeout);
  191.         if (c == 0)
  192.             break;
  193.         c &= 0177;
  194.         for (i = 0; i < strlen(match); i++)
  195.             if (c == match[i])
  196.                 status = c;
  197.     } while (status == 0);
  198.     if (debug) {
  199.         (void) fprintf(stderr, "\"\n");
  200.         (void) fflush(stderr);
  201.     }
  202.     return (status);
  203. }
  204.  
  205. error_rep(c)
  206.     register char c;
  207. {
  208.     printf("\n\r");
  209.     switch (c) {
  210.  
  211.     case '0':
  212.         printf("OK");
  213.         break;
  214.  
  215.     case '1':
  216.         printf("CONNECT");
  217.         break;
  218.     
  219.     case '2':
  220.         printf("RING");
  221.         break;
  222.     
  223.     case '3':
  224.         printf("NO CARRIER");
  225.         break;
  226.     
  227.     case '4':
  228.         printf("ERROR in input");
  229.         break;
  230.     
  231.     case '5':
  232.         printf("CONNECT 1200");
  233.         break;
  234.     
  235.     default:
  236.         printf("Unknown Modem error: %c (0x%x)", c, c);
  237.     }
  238.     printf("\n\r");
  239.     return;
  240. }
  241.  
  242. /*
  243.  * set modem back to normal verbose status codes.
  244.  */
  245. goodbye()
  246. {
  247.     int len, rlen;
  248.     char c;
  249.  
  250.     ioctl(FD, TIOCFLUSH, &len);    /* get rid of trash */
  251. /* XXX should really try to make this code work */
  252. #ifdef notdef
  253.     if (hay_sync()) {
  254.         sleep(1);
  255. #ifndef DEBUG
  256.         ioctl(FD, TIOCFLUSH, 0);
  257. #endif
  258.         hywrite("ATH0\r");        /* insurance */
  259. #ifndef DEBUG
  260.         c = gobble("03");
  261.         if (c != '0' && c != '3') {
  262.             printf("cannot hang up modem\n\r");
  263.             printf("please use 'tip dialer' to make sure the line is hung up\n\r");
  264.         }
  265. #endif
  266.         sleep(1);
  267.         ioctl(FD, FIONREAD, &len);
  268. #ifdef DEBUG
  269.         printf("goodbye1: len=%d -- ", len);
  270.         rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
  271.         dumbuf[rlen] = '\0';
  272.         printf("read (%d): %s\r\n", rlen, dumbuf);
  273. #endif
  274.         hywrite("ATv1\r");
  275.         sleep(1);
  276. #ifdef DEBUG
  277.         ioctl(FD, FIONREAD, &len);
  278.         printf("goodbye2: len=%d -- ", len);
  279.         rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
  280.         dumbuf[rlen] = '\0';
  281.         printf("read (%d): %s\r\n", rlen, dumbuf);
  282. #endif
  283.     }
  284.     ioctl(FD, TIOCFLUSH, 0);    /* clear the input buffer */
  285.     ioctl(FD, TIOCCDTR, 0);        /* clear DTR (insurance) */
  286.     close(FD);
  287. #endif
  288. }
  289.  
  290. #define MAXRETRY    5
  291.  
  292. hay_sync()
  293. {
  294.     int len, retry = 0;
  295.     char buf[32];
  296.  
  297.     while (retry++ <= MAXRETRY) {
  298.         hywrite("AT\r");
  299. #ifdef notdef
  300.         sleep(1);
  301. #endif
  302.         if (hyread(buf, CMD_DELAY, sizeof(buf)) &&
  303.             strcmp(buf, "AT\r") == 0 &&
  304.             hyread(buf, CMD_DELAY, sizeof(buf))) {
  305.             /* Still in terse mode */
  306.             if (strcmp(buf, "0\r") == 0)
  307.                 return(1);
  308.             /* Must be in verbose mode */
  309.             if (strcmp(buf, "\r") == 0 &&
  310.                 hyread(buf, CMD_DELAY, sizeof(buf)) &&
  311.                 strcmp(buf, MDM_OK) == 0)
  312.                 return(1);
  313.         }
  314.         ioctl(FD, TIOCCDTR, 0);
  315.         ioctl(FD, TIOCSDTR, 0);
  316.     }
  317.     printf("Cannot synchronize with hayes...\n\r");
  318.     return(0);
  319. }
  320.  
  321. static void
  322. hyerrputc(c)
  323.     char c;
  324. {
  325.  
  326.     if (c & ~0177) {
  327.         putc('M', stderr);
  328.         putc('-', stderr);
  329.         c &= 0177;
  330.     }
  331.     switch (c) {
  332.  
  333.     case '\r':
  334.         putc('\\', stderr);
  335.         putc('r', stderr);
  336.         break;
  337.  
  338.     case '\n':
  339.         putc('\\', stderr);
  340.         putc('n', stderr);
  341.         break;
  342.  
  343.     case '\t':
  344.         putc('\\', stderr);
  345.         putc('t', stderr);
  346.         break;
  347.  
  348.     default:
  349.         if (c < 0x20) {
  350.             putc('^', stderr);
  351.             putc(c + 0x40, stderr);
  352.         } else
  353.             putc(c, stderr);
  354.     }
  355.     (void) fflush(stderr);
  356. }
  357.  
  358. static void
  359. hyerrputs(s)
  360.     register char *s;
  361. {
  362.  
  363.     while (*s)
  364.         hyerrputc(*s++);
  365. }
  366.  
  367.  
  368. static void
  369. hyputc(c)
  370.     char c;
  371. {
  372.     struct timeval t;
  373.  
  374.     if (write(FD, &c, 1) != 1) {
  375.         perror("tip: hyputc: write error");
  376.         return;
  377.     }
  378.     if (debug)
  379.         hyerrputc(c);
  380.     t.tv_sec = 0;
  381.     t.tv_usec = WRITE_DELAY * 1000000;
  382.     (void) select(32, 0, 0, 0, &t);
  383. }
  384.  
  385. static void
  386. hywrite(cp)
  387.     register char *cp;
  388. {
  389.  
  390.     if (debug) {
  391.         (void) fprintf(stderr, "-> \"");
  392.         (void) fflush(stderr);
  393.     }
  394.     while (*cp != '\0')
  395.         hyputc(*cp++);
  396.     if (debug) {
  397.         (void) fprintf(stderr, "\"\n");
  398.         (void) fflush(stderr);
  399.     }
  400. }
  401.  
  402. static char
  403. hygetc(timeout)
  404.     unsigned int timeout;
  405. {
  406.     int n;
  407.     char c;
  408.     struct timeval t;
  409.     int readfds;
  410.  
  411.     t.tv_sec = timeout;
  412.     t.tv_usec = 0;
  413.     readfds = 1 << FD;
  414.     if ((n = select(FD+1, &readfds, 0, 0, &t)) <= 0) {
  415.         if (n < 0)
  416.             perror("hygetc: select");
  417.         return (0);
  418.     }
  419.     if ((n = read(FD, &c, 1)) <= 0) {
  420.         perror("hygetc: read");
  421.         return (0);
  422.     }
  423.     if (debug)
  424.         hyerrputc(c);
  425.     return (c);
  426. }
  427.  
  428. /*
  429.  * Read a line from the telebit. We assume a line will end
  430.  * with carriage return.
  431.  */
  432. static int
  433. hyread(buf, timeout, max)
  434.     char *buf;
  435.     unsigned int timeout, max;
  436. {
  437.     char *cp = buf;
  438.     char c;
  439.     int ret = 1;
  440.     static int failed = 0;
  441.  
  442.     if (debug) {
  443.         (void) fprintf(stderr, "<- \"");
  444.         (void) fflush(stderr);
  445.     }
  446.     *buf = '\0';
  447.  
  448.     /* grab everything up to the next \n */
  449.     while (cp < &buf[max - 2] && (*cp++ = c = hygetc(timeout)) != '\r')
  450.         if (c == 0) {
  451.             ret = 0;
  452.             goto bail;
  453.         }
  454.     *cp = '\0';
  455.  
  456. bail:
  457.     if (debug) {
  458.         (void) fprintf(stderr, "\"\n");
  459.         (void) fflush(stderr);
  460.     }
  461.     return(ret);
  462. }
  463.